package club.monkeywood.transaction.order.service;


import club.monkeywood.transaction.order.dao.OrderRepository;
import club.monkeywood.transaction.order.domain.Order;
import club.monkeywood.transaction.order.dto.OrderDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.ZonedDateTime;
import java.util.List;
import java.util.Optional;

@Service
@Slf4j
public class OrderService {

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    private OrderRepository orderRepository;

    @Transactional
    @RabbitListener(queuesToDeclare = @Queue("order:lock"))
    public void handleTicketLock(OrderDTO dto){
        log.info("Got new order to create:{}", dto);
        Order orderByUuid = orderRepository.findByUuid(dto.getUuid());
        if(orderByUuid!=null){
            log.info("Msg already processed!", dto);
        }else {
            Order order = createOrder(dto);
            Order save = orderRepository.save(order);
            dto.setId(save.getId());
        }
        dto.setStatus("NEW");
        amqpTemplate.convertAndSend("order:pay",dto);

    }

    @Transactional
    @RabbitListener(queuesToDeclare = @Queue("order:finish"))
    public void handleOrderFinish(OrderDTO dto){
        log.info("获得消息:order:finish:{}", dto);
        Order order = orderRepository.findById(dto.getId()).orElse(null);
        order.setStatus("FINISH");
        orderRepository.save(order);

    }

    @Transactional
    @RabbitListener(queuesToDeclare = @Queue("order:fail"))
    public void handleOrderFail(OrderDTO dto){
        log.info("获得消息:order:fail:{}", dto);
        Order order=null;
        //锁票失败处理
        if(dto.getId() == null){
            order = createOrder(dto);
            order.setStatus("FAIL");
            order.setReason("TICKET_LOCK_FAIL");
            orderRepository.saveAndFlush(order);
            return;
        }

        order = orderRepository.findById(dto.getId()).orElse(null);
        if(order==null){
            log.warn("订单不存在:{}",dto);
            return;
        }

        if(dto.getStatus().equals("NOT_ENOUGH_DEPOSIT")){
            order.setReason("NOT_ENOUGH_DEPOSIT");
            order.setStatus("FAIL");
            orderRepository.saveAndFlush(order);
            return;
        }

        if(dto.getStatus().equals("TIMEOUT")){
            order.setReason("TIMEOUT");
            order.setStatus("FAIL");
            orderRepository.saveAndFlush(order);
            return;
        }
    }

    //处理超时订单
    //order.status:既不是NEW，也不是FAIL
    //fixedDelay:上次执行完成后延迟，单位:ms
    @Scheduled(fixedDelay = 10000L)
    public void checkTimeoutOrders(){
        ZonedDateTime checkTime = ZonedDateTime.now().minusMinutes(1L);
        List<Order> orders = orderRepository.findByStatusAndCreatedDateBefore("NEW", checkTime);
        orders.forEach(order -> {
            log.error("Order timeout:{}",order);
            OrderDTO dto = new OrderDTO();
            BeanUtils.copyProperties(order,dto);
            dto.setStatus("TIMEOUT");
            amqpTemplate.convertAndSend("order:fail",dto);
        });
    }

    private Order createOrder(OrderDTO dto){
        Order order = new Order();
        order.setUuid(dto.getUuid());
        order.setAmount(dto.getAmount());
        order.setTitle(dto.getTitle());
        order.setCustomerId(dto.getCustomerId());
        order.setTicketNum(dto.getTicketNum());
        order.setStatus("NEW");
        order.setCreatedDate(ZonedDateTime.now());
        return order;
    }

}
